package com.tiny_wind.tiny_wind_diary.controller;

import com.auth0.jwt.interfaces.Claim;
import com.tiny_wind.tiny_wind_diary.entity.TokenEntity;
import com.tiny_wind.tiny_wind_diary.entity.UserEntity;
import com.tiny_wind.tiny_wind_diary.model.TwErrorModel;
import com.tiny_wind.tiny_wind_diary.model.TwResultModel;
import com.tiny_wind.tiny_wind_diary.service.impl.UserServiceImpl;
import com.tiny_wind.tiny_wind_diary.utility.GaJJwtManager;
import com.tiny_wind.tiny_wind_diary.utility.GaLogManager;
import com.tiny_wind.tiny_wind_diary.utility.GaTimeManager;
import com.tiny_wind.tiny_wind_diary.utility.ResponseCodeManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import java.util.Map;

@RestController
@CrossOrigin
@RequestMapping("/User")
public class UserController extends BaseController {
    public static String TAG = "UserController";
    private Logger logger = LogManager.getLogger(this.getClass());

    @Autowired
    private UserServiceImpl mService;

    @RequestMapping(value = "/Login", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<UserEntity> login(@RequestBody UserEntity filter) {
        logger.debug("UserController/login,account:{},password:***", filter.account);
        try {
            UserEntity entity = mService.search(filter.account);
            //用户不存在. -1;
            if (entity == null) {
                logger.debug("no such account");
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(-1, "No such account");
                return result;
            }
            /**
             * 对比密码,不区分大小写.
             */
            if (entity.password.toLowerCase().equals(filter.password.toLowerCase())) {
                logger.debug("password match");
                String token = storeToken(entity.account, entity.id);
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(entity);
                entity.token = token;
                Cookie cookie = new Cookie("token", token);
                cookie.setPath("/");
                cookie.setMaxAge(7200);
                response.addCookie(cookie);
                return result;
            } else {
                logger.debug("password mismatch");
                TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(-2, "账号或者密码错误");
                return result;
            }
        } catch (Exception e) {
            logger.debug("TodoController/search exception,%s", e.getMessage());
            e.printStackTrace();
            return null;
        }

    }


    /**
     * 通过Token登录,换取新Token.
     * token已参数形式传递过来.
     *
     * @param filter {userId=""}
     * @return
     */
    @RequestMapping(value = "/Login/Token", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<UserEntity> loginWithToken(@RequestBody UserEntity filter) {
        logger.info("UserController/loginWithToken");
        Integer userId = this.getUserId();
        Integer _userId = filter.id;
        if (_userId == null) {
            logger.warn("no user id");
            return new TwResultModel<UserEntity>(TwErrorModel.MissingNonNullRequestParam("id"));
        }
        if (userId != _userId) {
            logger.warn("user id not match");
            return new TwResultModel<UserEntity>(TwErrorModel.InvalidToken());
        }
        UserEntity user = mService.searchByUserId(userId);
        //重新生成token并保存.
        String token = storeToken(user.account, user.id);
        TwResultModel<UserEntity> result = new TwResultModel<UserEntity>(user);
        user.token = token;
        Cookie cookie = new Cookie("token", token);
        cookie.setPath("/");
        cookie.setMaxAge(7200);
        response.addCookie(cookie);
        return result;
    }

    /**
     * 1,生成一个token,插入到表中.
     * 2,返回该token.
     *
     * @param userAccount
     * @param userId
     * @return
     */
    public String storeToken(String userAccount, Integer userId) {
        String token = GaJJwtManager.generatorToken(userAccount, userId);
        String info = String.format("UserController/storeToken,token is: %s", token);
        logger.info(info);
        String expireTime = GaTimeManager.sharedInstance.stdTimeStringAfterNow(GaJJwtManager.ms_expireTime);
        TokenEntity entity = new TokenEntity(token, userId, expireTime);
        try {
            mService.insertToken(entity);
        } catch (Exception e) {
            //重复插入.
            info = e.getLocalizedMessage();
            logger.warn(info);
        }
        return token;
    }


    @RequestMapping(value = "/NoToken", method = RequestMethod.GET)
    @ResponseBody
    public TwResultModel<Object> noToken(int code) {
        GaLogManager.v_c(TAG, "Path", "noToken");
        return new TwResultModel<Object>(ResponseCodeManager.errorCode_noToken, ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_noToken));
    }

    @RequestMapping(value = "/NoToken", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<Object> noToken_post() {
        GaLogManager.v_c(TAG, "Path", "noToken_post");
        return new TwResultModel<Object>(ResponseCodeManager.errorCode_noToken, ResponseCodeManager.getCodeMessage(ResponseCodeManager.errorCode_noToken));
    }

    /**
     * 注销.
     * 1,清除当前的token.
     *
     * @return
     */
    @RequestMapping(value = "/Logout", method = RequestMethod.POST)
    @ResponseBody
    public TwResultModel<Object> logout(@RequestBody UserEntity filter) {
        logger.info("UserController/logout");
        Integer userId = this.getUserId();
        Integer _userId = filter.id;
        if (_userId == null) {
            logger.warn("no user id");
            return new TwResultModel<Object>(TwErrorModel.MissingNonNullRequestParam("id"));
        }
        if (userId != _userId) {
            logger.warn("user id not match");
            return new TwResultModel<Object>(TwErrorModel.InvalidToken());
        }
        mService.clearToken(userId);
        return new TwResultModel<Object>();
    }
}